package uniquecode

import (
	"context"
	"gitee.com/bobo-rs/creative-framework/pkg/utils"
	"github.com/gogf/gf/v2/os/gcache"
	"github.com/gogf/gf/v2/os/gtime"
	"regexp"
	"strconv"
	"time"
)

const (
	CacheUniCodeKey = "unique.serial_code.rid_of_map:"
)

// UniSerialCode 生成有序唯一编号
func UniSerialCode(ctx context.Context, prefix string, isRidOfs ...bool) (uniCode string) {
	// 唯一值前缀
	prefix += time.Now().Format("20060102150405")
	var (
		cacheKey = CacheUniCodeKey + prefix
		ridOfMap = make(map[string]interface{})
		isRidOf  bool
		loop     uint
	)

	// 是否缓存
	if len(isRidOfs) > 0 && isRidOfs[0] {
		isRidOf = true
		if r, _ := gcache.Get(ctx, cacheKey); !r.IsEmpty() {
			ridOfMap = r.Map()
		}
	}

	// 循环生产编号，最多100次
	for {
		uniCode = prefix + strconv.Itoa(utils.RandomInt(100000, 999999))
		if loop > 100 || !isRidOf {
			// 检测无缓存，没重复值
			if _, ok := ridOfMap[uniCode]; ok {
				loop++
				continue
			}
			// 记录生成值
			ridOfMap[uniCode] = 1
			break
		}
		loop++
	}
	// 是否缓存，默认患者一天
	if isRidOf {
		_ = gcache.Set(ctx, cacheKey, ridOfMap, gtime.D)
	}
	return
}

// CheckUniqueCode 验证编号的有效性
func CheckUniqueCode(code string, isPrefix ...bool) bool {
	// 默认只匹配数字部分
	pattern := `^[\d]{20}$`
	if len(isPrefix) > 0 && isPrefix[0] {
		pattern = `^[a-zA-Z]+\d{20}$`
	}
	return regexp.MustCompile(pattern).MatchString(code)
}
